package com.reactlibrary.rn;

import android.app.Activity;
import android.content.Intent;
import android.support.annotation.NonNull;


import com.facebook.react.bridge.ActivityEventListener;
import com.facebook.react.bridge.Arguments;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.stripe.android.ApiResultCallback;
import com.stripe.android.PaymentIntentResult;
import com.stripe.android.SetupIntentResult;
import com.stripe.android.Stripe;
import com.stripe.android.model.ConfirmPaymentIntentParams;
import com.stripe.android.model.ConfirmSetupIntentParams;
import com.stripe.android.model.PaymentIntent;
import com.stripe.android.model.PaymentMethod;
import com.stripe.android.model.PaymentMethodCreateParams;
import com.stripe.android.model.SetupIntent;
import java.util.Objects;

/**
 * @author 李顺风
 * @date 3/26/21.
 * GitHub：https://github.com/hotdog45
 * email：mac2020@126.com
 * description：coding
 */
class StripeManager extends ReactContextBaseJavaModule {
    private static ReactApplicationContext reactContext;
    private final ActivityEventListener mActivityEventListener = new BaseActivityEventListener() {
        private static Stripe mStripe;

        @Override
        public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {

            mStripe.onSetupResult(requestCode, data, new ApiResultCallback<SetupIntentResult>() {
                @Override
                public void onSuccess(@NonNull SetupIntentResult result) { //confirmSetupIntent
                    SetupIntent setupIntent = result.getIntent();
                    SetupIntent.Status status = setupIntent.getStatus();
                    WritableMap currentParams = Arguments.createMap();

                    if (status == PaymentIntent.Status.Succeeded) {
                        currentParams.putString("code","1");
                        currentParams.putString("localizedDescription","Succeeded");
                        sendEvent(reactContext, "confirmSetupIntent", currentParams);
                    } else if (status == PaymentIntent.Status.Canceled) {
                        currentParams.putString("code","2");
                        currentParams.putString("localizedDescription","Canceled");
                        sendEvent(reactContext, "confirmSetupIntent", currentParams);

                    } else {
                        currentParams.putString("code","3");
                        currentParams.putString("localizedDescription",
                                Objects.requireNonNull(setupIntent.getLastSetupError()).getMessage()
                        );
                        sendEvent(reactContext, "confirmSetupIntent", currentParams);
                    }
                }

                @Override
                public void onError(@NonNull Exception e) {
                    WritableMap currentParams = Arguments.createMap();

                    currentParams.putString("code","3");
                    currentParams.putString("localizedDescription","" );
                    sendEvent(reactContext, "confirmSetupIntent", currentParams);

                }
            });
             mStripe.onPaymentResult(requestCode, data, new ApiResultCallback<PaymentIntentResult>() {

                @Override
                public void onSuccess(@NonNull PaymentIntentResult result) {
                    PaymentIntent paymentIntent = result.getIntent();
                    PaymentIntent.Status status = paymentIntent.getStatus();
                    WritableMap currentParams = Arguments.createMap();

                    if (status == PaymentIntent.Status.Succeeded) {
                        currentParams.putString("code","1");
                        currentParams.putString("localizedDescription","Succeeded");
                        sendEvent(reactContext, "confirmPayment", currentParams);

                    } else if (status == PaymentIntent.Status.Canceled) {
                        currentParams.putString("code","2");
                        currentParams.putString("localizedDescription","Canceled");
                        sendEvent(reactContext, "confirmPayment", currentParams);

                    } else {
                        currentParams.putString("code","3");
                        currentParams.putString("localizedDescription",
                                Objects.requireNonNull(paymentIntent.getLastPaymentError()).getMessage()
                                );
                        sendEvent(reactContext, "confirmPayment", currentParams);
                    }

                }

                @Override
                public void onError(@NonNull Exception e) {
                    WritableMap currentParams = Arguments.createMap();
                    currentParams.putString("code","3");
                    currentParams.putString("localizedDescription","" );
                    sendEvent(reactContext, "confirmPayment", currentParams);

                }
            });

        }
    };

    public StripeManager(ReactApplicationContext context) {
        super(context);
        reactContext = context;
        reactContext.addActivityEventListener(mActivityEventListener);
//        reactContext.removeActivityEventListener(mActivityEventListener);
    }

    @NonNull
    @Override
    public String getName() {
        return "StripeManager";
    }

    @ReactMethod
    public void addEvent(String message, ReadableMap map) {
//        sendEvent(reactContext, "confirmSetupIntent", map);

        String clientSecret =  map.getString("clientSecret");
        String publishableKey =  map.getString("publishableKey");
        boolean isBindCard =  map.getBoolean("isBindCard");
        String number =  map.getString("number");
        int expYear =  map.getInt("expYear");
        int expMonth =  map.getInt("expMonth");
        String cvc =  map.getString("cvc");
        String paymentMethodId =  map.getString("paymentMethodId");


        MainApplication.mStripe = new Stripe(getReactApplicationContext(), publishableKey);

//        MainApplication.mStripe

        PaymentMethodCreateParams.Card card =  new PaymentMethodCreateParams.Card.Builder()
                .setCvc(cvc)
                .setExpiryMonth(expMonth)
                .setNumber(number)
                .setExpiryYear(expYear)
                .build();


        if (message.equals("confirmSetupIntent")){ ////绑卡
            PaymentMethod.BillingDetails billingDetails =
                    new PaymentMethod.BillingDetails.Builder().build();

            PaymentMethodCreateParams paymentMethodParams = PaymentMethodCreateParams
                    .create(card, billingDetails);
            ConfirmSetupIntentParams confirmParams = ConfirmSetupIntentParams
                    .create(paymentMethodParams, clientSecret);
            MainApplication.mStripe.confirmSetupIntent(reactContext.getCurrentActivity(), confirmParams);
        }

        if (message.equals("confirmPayment")){ // 支付
            PaymentMethod.BillingDetails billingDetails =
                    new PaymentMethod.BillingDetails.Builder().build();
            PaymentMethodCreateParams paymentMethodParams = PaymentMethodCreateParams
                    .create(card, billingDetails);
            ConfirmPaymentIntentParams confirmParams;

            if (paymentMethodId !=null && paymentMethodId.length()>5){
                confirmParams = ConfirmPaymentIntentParams
                        .createWithPaymentMethodId(paymentMethodId,clientSecret);
            }else {
                 confirmParams = ConfirmPaymentIntentParams
                        .createWithPaymentMethodCreateParams(paymentMethodParams, clientSecret);
            }

            if (isBindCard){
                confirmParams.setSetupFutureUsage(ConfirmPaymentIntentParams.SetupFutureUsage.OffSession);
            }


            MainApplication.mStripe.confirmPayment(reactContext.getCurrentActivity(), confirmParams);
        }

    }

    private void sendEvent(ReactContext reactContext,
                           String eventName,
                           WritableMap params) {
        reactContext
                .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit(eventName, params);
    }

}
